<?php

/**
* @package plugin ScriptsDown
* @copyright (C) 2010-2011 RicheyWeb - www.richeyweb.com
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* ScriptsDown Copyright (c) 2010 Michael Richey.
* ScriptsDown is licensed under the http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
*
* ScriptsDown version 1.6 for Joomla 1.5.x devloped by RicheyWeb
*
*/
// no direct access
defined( '_JEXEC' ) or die( 'Restricted access' );

jimport( 'joomla.plugin.plugin' );

/**
 * ScriptsDown system plugin
 */
class plgSystemScriptsDown extends JPlugin
{
	var $_buffer = null;
	var $_scripts = array();
	var $_omit = array();
	/**
	 * Constructor
	 *
	 * @access	protected
	 * @param	object	$subject The object to observe
	 * @param 	array   $config  An array that holds the plugin configuration
	 * @since	1.0
	 */
	function plgSystemScriptsDown( &$subject, $config )
	{
		parent::__construct( $subject, $config );
	}
	
	/* The scripts are all present after the document is rendered */
	function onAfterRender()
	{
		/* test that the page is not administrator */
		$app =& JFactory::getApplication();
		if ($app->isAdmin()) {
			return;
		}
		/* test that the document is HTML output */
		$document =& JFactory::getDocument();
		if($document->getType() != 'html') {
			return;
		}
		foreach (explode("\n",$this->params->get('omit')) as $omit) {
			$this->_omit[] = '/'.str_replace(array('/','\''),array('\/','\\\''),trim($omit)).'/i';
		}
		$this->_buffer = JResponse::getBody();
		if($this->extractscripts()) JResponse::setBody($this->_buffer);
	}
	function extractscripts() {
		$regscripta='/<script/i';
		$regscriptb='/<\/script>/i';
		$regifa='/<!.*\[if.*\].*>/i';
		$regifb='/<!.*\[endif\].*>/i';
		$style='/<style>/i';
		$link='/<link/i';
		$endhead='/<\/head>/';
		preg_match_all($regscripta,$this->_buffer,$scripta,PREG_OFFSET_CAPTURE);
		$scripta['scripta']=$scripta[0]; unset($scripta[0]);
		preg_match_all($regscriptb,$this->_buffer,$scriptb,PREG_OFFSET_CAPTURE);
		foreach (array_keys($scriptb[0]) as $key) $scriptb[0][$key][1] = $scriptb[0][$key][1] + strlen($scriptb[0][$key][0]); unset($key);
		$scriptb['scriptb']=$scriptb[0]; unset($scriptb[0]);
		for ($i=0;$i<count($scripta['scripta']);$i++) $script[$i]=array('start'=>$scripta['scripta'][$i][1],'end'=>$scriptb['scriptb'][$i][1]);
		preg_match_all($regifa,$this->_buffer,$ifa,PREG_OFFSET_CAPTURE);
		$ifa['ifa']=$ifa[0]; unset($ifa[0]);
		preg_match_all($regifb,$this->_buffer,$ifb,PREG_OFFSET_CAPTURE);
		foreach (array_keys($ifb[0]) as $key) $ifb[0][$key][1] = $ifb[0][$key][1] + strlen($ifb[0][$key][0]); unset($key);
		$ifb['ifb']=$ifb[0]; unset($ifb[0]);
		preg_match($endhead,$this->_buffer,$endheadpos,PREG_OFFSET_CAPTURE);
		$endhead=$endheadpos[0][1];
		for ($i=0;$i<count($ifa['ifa']);$i++) $if[$i]=array('start'=>$ifa['ifa'][$i][1],'end'=>$ifb['ifb'][$i][1]);
		if(count($if)) {
			foreach($if as $ifrange) {
				if (!preg_match($style,substr($this->_buffer,$ifrange['start'],$ifrange['end']-$ifrange['start'])) AND !preg_match($link,substr($this->_buffer,$ifrange['start'],$ifrange['end']-$ifrange['start'])) AND $ifrange['start'] < $endhead) {
					foreach(array_keys($script) as $key) {
						if ($script[$key]['start'] > $ifrange['start'] AND $script[$key]['end'] < $ifrange['end']) {
							unset($script[$key]);
						}
					}
					$positions[$ifrange['start']]=$ifrange['start'];
					$positions[$ifrange['end']]=$ifrange['end'];
				}
			}
		}
		if(count($script)) {
			foreach($script as $scriptrange) {
				if($scriptrange['start'] < $endhead) {
					$positions[$scriptrange['start']]=$scriptrange['start'];
					$positions[$scriptrange['end']]=$scriptrange['end'];
				}
			}
		}
		if(count($positions)) {
			krsort($positions);
			while(count($positions)) {
				$start=array_pop($positions);
				$end=array_pop($positions);
				$length = $end - $start;
				$range[]=array('start'=>$start,'end'=>$end);
				$script=substr($this->_buffer,$start,$length);
				$omitme=false;
				foreach ($this->_omit as $omit) if ($omitme === false) $omitme=(bool)preg_match($omit,$script);
				if (!$omitme) {
					$this->_scripts[]=$script;
				} else {
					array_pop($range);
				}
			}
			$newbuffer='';
			$firstline=substr($this->_buffer,0,$range[0]['start']-1);
			$newbuffer.=$firstline;
			for($i=0;$i<count($range)-1;$i++) {
				$line=substr($this->_buffer,$range[$i]['end'],($range[($i+1)]['start']-$range[$i]['end']));
				$newbuffer.=$line;
			}
			$lastline=substr($this->_buffer,$range[count($range)-1]['end']);
			$newbuffer.=$lastline;
			$this->_buffer=$newbuffer;
			$this->_scripts=implode("\n",$this->_scripts);
			$pos = stripos($this->_buffer, '</body');
			$this->_buffer = substr($this->_buffer,0,$pos).$this->_scripts.substr($this->_buffer,$pos);
			return true;
		} else {
			return false;
		}
	}
}